#include <kew/c-vm.h>

/* This creates a new Sandbox and associates with it a check block that can veto any access
 * that is requested.
 * A note on the runtime system: whenever a new Sandbox context is established, Kew inhibits any
 * operations that might violate encapsulation and thus allow access to objects from the parent's
 * more privileged context. Thus, for example, reflection will not work on any object from the parent,
 * though you can still send such objects messages if you have references to them.
 */

KEW_METHOD(Sandbox_new) /* :VetoBlock ^NewSandbox */
{
    KewSandboxObject *new_sandbox = kew_sandbox_new();
    new_sandbox->parent = receiver;
    new_sandbox->block = args[0];
    results[0] = new_sandbox;
}

/* This allows for a security access check from within the environment.
 *
 * This is called (mainly by the Kew VM) to ensure that one security domain has the right to
 * do something sensitive in the other. It boils down to which security domain "owns" the other.
 */

void kew_sandbox_check(KewSandboxObject *source, KewSandboxObject *dest)
{
    /* Root security context is allowed to access anything BUT make sure you're not just passing
     * in uninitialized data here.
     */
    if (source == NULL)
        return TRUE;

    /* Otherwise, chase up the security domain hierarchy in the destination, and look for the source
     * (i.e. verify source is actually a parent of dest)
     */    
    while (dest != NULL && dest != source)
        dest = dest->parent;

    /* If we've visited all the parents of dest and didn't find source, access is not allowed. */
    if (dest != NULL)
        kew_send(receiver->block, kew_sel_call, kew_shape__, NULL, NULL);
}
